﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Security.Cryptography;
using System.Xml.Linq;
using System.ServiceModel;
using DevWeb.Biztalk.DeploymentSettings.Common;
using DevWeb.Biztalk.DeploymentSettings.Data.CodeFirst;
using DevWeb.Biztalk.DeploymentSettings.Data.CodeFirst.Context;
using DevWeb.Biztalk.DeploymentSettings.DeploymentService;
using DevWeb.Biztalk.DeploymentSettings.DeploymentService.Contracts;
using DevWeb.Biztalk.DeploymentSettings.DeploymentService.Contracts.Faults;
using DevWeb.Biztalk.DeploymentSettings.DeploymentService.Contracts.Model;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;


namespace DeploymentService
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class DeploymentSettingsService : IDeploymentSettingsService
    {
       // private static UnityServiceHost host;

        
        private DeploymentSettingsContext context = new DeploymentSettingsContext();




        public ExportModel GetEnvironmentSettings(Guid productupgradecode, Guid productid, string environment)
        {
            //var settings =
            //    context.IntegrationVersionParameters.Include("IntegrationVersion")
            //        .Include("IntegrationVersion.Integration")
            //        .Include("IntegrationVersionParameterValues")
            //        .Where(p => p.IntegrationVersion.ProductId.Equals(productid))
            //        .ToList();

            var intversion =
                context.IntegrationVersions.Include("Integration")
                    .Include("IntegrationVersionParameters")
                    .Include("IntegrationVersionParameters.IntegrationVersionParameterValues")
                    .SingleOrDefault(p => p.ProductId.Equals(productid));

            if (intversion==null)
                throw new ArgumentException(string.Format("There is no integrationversion found with ProdutID {0}",productid.ToString()));
            
            var model = new ExportModel();
            

            model.IntegrationDescription = intversion.Integration.Description;
            model.Name = intversion.IntegrationName;
            model.ProductId = intversion.ProductId;
            model.ProductUpgradeCode = intversion.ProductUpgradeCode;
            model.CreateDateTime = intversion.CreateDateTime;
            model.Description = intversion.Description;
            model.ExportParameters = new List<ExportParameter>();
            model.Version = intversion.Version;

            var targetenv = context.TargetEnvironments.SingleOrDefault(p => p.Name.Equals(environment));

            
            foreach (var integrationVersionParameter in intversion.IntegrationVersionParameters)
            {

                var query = from p in integrationVersionParameter.IntegrationVersionParameterValues
                            where p.TargetEnvironmentId.Equals(targetenv.Id)
                            select p;


                ExportParameter param = new ExportParameter();
                param.DefaultValue = integrationVersionParameter.DefaultValue;
                param.ParameterName = integrationVersionParameter.ParameterName;
                param.ParameterValues = new List<ExportParameterValue>();

                foreach (var parameterValue in query.ToList())
                {
                    ExportParameterValue value = new ExportParameterValue(parameterValue);
                    param.ParameterValues.Add(value);
                }

                model.ExportParameters.Add(param);
            }

            var defaultsettings = context.DefaultSettingParameters.Include("DefaultSettingParameterValues").ToList();
            foreach (var defaultSettingParameter in defaultsettings)
            {
                ExportParameter param = new ExportParameter();
                param.DefaultValue = defaultSettingParameter.DefaultValue;
                param.ParameterName = defaultSettingParameter.ParameterName;
                param.IsDefaultValue = true;
                param.ParameterValues = new List<ExportParameterValue>();

                var query = from p in defaultSettingParameter.DefaultSettingParameterValues
                            where p.TargetEnvironmentId.Equals(targetenv.Id)
                            select p;

                foreach (var parameterValue in query.ToList())
                {
                    ExportParameterValue value = new ExportParameterValue();
                    value.Environment = targetenv.Name;
                    value.Value = parameterValue.Value;
                    param.ParameterValues.Add(value);
                }
                model.ExportParameters.Add(param);
            }


            return model;
        }

        public bool LogDeployment(string machinename, string username, string deploymenttype, Guid productid, Guid productupgradecode, string environment)
        {
            var targetenv = context.TargetEnvironments.SingleOrDefault(p => p.Name.Equals(environment));
            var integrationversion = context.IntegrationVersions.Single(p => p.ProductId.Equals(productid));


            if (targetenv == null)
            {
                var fault = new  SystemFault(String.Format("Environment {0} not found", environment)) { FaultCode = 10, Identifier = "Environment", ObjectType = "Environment" };
                throw new FaultException<SystemFault>(fault);
            }
            DeploymentLog log = new DeploymentLog();
            log.DeployedBy = username;
            log.CreateDateTime = DateTime.Now;
            log.MachineName = machinename;
            log.Type = deploymenttype;
            log.IntegrationVersionId = integrationversion.Id;
            log.TargetEnvironmentId = targetenv.Id;

            context.DeploymentLogs.Add(log);
            context.SaveChanges(username);
            return true;
        }
    }
}